home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
- * the contents of this file may not be disclosed to third parties, copied or
- * duplicated in any form, in whole or in part, without the prior written
- * permission of Silicon Graphics, Inc.
- *
- * RESTRICTED RIGHTS LEGEND:
- * Use, duplication or disclosure by the Government is subject to restrictions
- * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
- * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
- * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
- * rights reserved under the Copyright Laws of the United States.
- */
- /*
- * psbook -
- * A PostScript book generation program
- *
- * To compile:
- * cc psbook.c -o psbook
- *
- * Paul Haeberli - 1993
- */
- #include "stdio.h"
- #include "math.h"
- #include "ctype.h"
-
- /* printer specific tuning */
- #define FRONTXFUDGE (72.0*-0.020) /* front offset for our lazer printer */
- #define FRONTYFUDGE (72.0* 0.020)
- #define BACKXFUDGE (72.0* 0.010) /* back offset for our lazer printer */
- #define BACKYFUDGE (72.0* 0.070)
-
- /* paper specific tuning */
- #define CREAPPERSHEET (72.0*(0.04/6.0)) /* creap per sheet */
-
- #define DEFPWIDTH (72.0*8.50) /* page width and weight */
- #define DEFPHEIGHT (72.0*11.0)
-
- #define SWIDTH (72.0*8.50) /* sheet width and height */
- #define SHEIGHT (72.0*11.0)
-
- #define MARGIN (72.0*0.2) /* margin amount */
- #define SPMARGIN (72.0*0.25) /* page spread margin */
- #define BLEED (72.0*0.25) /* bleed amount */
-
- #define FRONTSIDE (0)
- #define BACKSIDE (1)
-
- #define RIGHTPAGE (0)
- #define LEFTPAGE (1)
- #define CENTERPAGE (2)
- #define SPRIGHTPAGE (3)
- #define SPLEFTPAGE (4)
-
- #define BOTSIG (0)
- #define TOPSIG (1)
-
- #define INBUFSIZE 4096
- #define MAXPAGES 1000
-
- #define FOLD0DX (SWIDTH)
- #define FOLD0DY (SHEIGHT)
-
- #define FOLD1DX (SHEIGHT/2.0-MARGIN)
- #define FOLD1DY (SWIDTH-2*MARGIN)
-
- #define FOLD2DX (SWIDTH/2.0-MARGIN)
- #define FOLD2DY (SHEIGHT/2.0-2*MARGIN)
-
- char buf[INBUFSIZE];
- int secstart[MAXPAGES];
- int secend[MAXPAGES];
- int trailstart;
- int trailend;
- float pdx, pdy, pscale;
- float pwidth, pheight, xoffset, yoffset, dxoffset;
-
- void printheader(dosettrans)
- int dosettrans;
- {
- printf("%%!PS-Adobe-2.0\n");
- printf("%%%%EndComments\n");
- printf("/REALshowpage /showpage load def\n");
- printf("/showpage { } def\n");
- if(dosettrans)
- psprintcortab();
- }
-
- int indexpages(inf)
- FILE *inf;
- {
- int i, n, before, after;
-
- n = 0;
- trailstart = 0;
- trailend = 0;
- while(fgets(buf,INBUFSIZE,inf)) {
- if(strncmp(buf,"%%Page:",7) == 0) {
- after = ftell(inf);
- if(n>0)
- secend[n-1] = before;
- secstart[n] = after;
- n++;
- } else if(strncmp(buf,"%%Trailer",9) == 0) {
- after = ftell(inf);
- if(n>0)
- secend[n-1] = before;
- trailstart = after;
- trailend = sizeoffile(inf);
- return n;
- }
- before = ftell(inf);
- }
- secend[n-1] = ftell(inf);
- return n;
- }
-
- void putsection(inf,start,nbytes)
- FILE *inf;
- int start, nbytes;
- {
- int nr;
-
- fseek(inf,start,0);
- while(nbytes>0) {
- if(!fgets(buf,INBUFSIZE,inf)) {
- fprintf(stderr,"psbook: bad read in putsection\n");
- exit(1);
- }
- nr = strlen(buf);
- nbytes -= nr;
- if(buf[0] != '%')
- fputs(buf,stdout);
- }
- if(nbytes != 0) {
- fprintf(stderr,"psbook: strange read in putsection %d\n",nbytes);
- exit(1);
- }
- }
-
- void putmark(x,y,rot)
- float x, y, rot;
- {
- printf("gsave\n");
- printf("0.1 setlinewidth\n");
- printf("%f %f translate\n",x,y);
- printf("%f rotate\n",rot);
- printf("newpath\n");
- printf("8 0 moveto\n");
- printf("40 0 lineto\n");
- printf("0 8 moveto\n");
- printf("0 40 lineto\n");
- printf("stroke\n");
- printf("grestore\n");
- }
-
- void putfold(x,y,rot)
- float x, y, rot;
- {
- printf("gsave\n");
- printf("0.1 setlinewidth\n");
- printf("%f %f translate\n",x,y);
- printf("%f rotate\n",rot);
- printf("newpath\n");
- printf("8 0 moveto\n");
- printf("40 0 lineto\n");
- printf("stroke\n");
- printf("grestore\n");
- }
-
- void xshift(page)
- int page;
- {
- float xoff, yoff;
-
- if(page&1)
- xoff = xoffset+dxoffset;
- else
- xoff = xoffset-dxoffset;
- yoff = yoffset;
- printf("%f %f translate\n",xoff,yoff);
- }
-
- void setclip(inf,page,spdx,spdy)
- FILE *inf;
- int page;
- float spdx, spdy;
- {
- switch(page) {
- case RIGHTPAGE:
- putfold(spdx/2.0,(spdy-pdy)/2.0,270.0);
- putfold(spdx/2.0,(spdy+pdy)/2.0,90.0);
- putmark(spdx/2.0+pdx,(spdy-pdy)/2.0,270.0);
- putmark(spdx/2.0+pdx,(spdy+pdy)/2.0,0.0);
- printf("%f %f translate\n",spdx/2.0,(spdy-pdy)/2.0);
- printf("%f %f scale\n",pscale,pscale);
- printf("newpath\n");
- printf("%f %f moveto\n",0.0,-BLEED);
- printf("%f %f lineto\n",pwidth+BLEED,-BLEED);
- printf("%f %f lineto\n",pwidth+BLEED,pheight+BLEED);
- printf("%f %f lineto\n",0.0,pheight+BLEED);
- printf("closepath clip newpath\n");
- break;
- case LEFTPAGE:
- putfold(spdx/2.0,(spdy-pdy)/2.0,270.0);
- putfold(spdx/2.0,(spdy+pdy)/2.0,90.0);
- putmark(spdx/2.0-pdx,(spdy-pdy)/2.0,180.0);
- putmark(spdx/2.0-pdx,(spdy+pdy)/2.0,90.0);
- printf("%f %f translate\n",spdx/2.0-pdx,(spdy-pdy)/2.0);
- printf("%f %f scale\n",pscale,pscale);
- printf("newpath\n");
- printf("%f %f moveto\n",-BLEED,-BLEED);
- printf("%f %f lineto\n",pwidth,-BLEED);
- printf("%f %f lineto\n",pwidth,pheight+BLEED);
- printf("%f %f lineto\n",-BLEED,pheight+BLEED);
- printf("closepath clip newpath\n");
- break;
- case CENTERPAGE:
- putmark((spdx+pdx)/2.0,(spdy+pdy)/2.0,0.0);
- putmark((spdx-pdx)/2.0,(spdy+pdy)/2.0,90.0);
- putmark((spdx-pdx)/2.0,(spdy-pdy)/2.0,180.0);
- putmark((spdx+pdx)/2.0,(spdy-pdy)/2.0,270.0);
- printf("%f %f translate\n",(spdx-pdx)/2.0,(spdy-pdy)/2.0);
- printf("%f %f scale\n",pscale,pscale);
- printf("newpath\n");
- printf("%f %f moveto\n",-BLEED,-BLEED);
- printf("%f %f lineto\n",pwidth+BLEED,-BLEED);
- printf("%f %f lineto\n",pwidth+BLEED,pheight+BLEED);
- printf("%f %f lineto\n",-BLEED,pheight+BLEED);
- printf("closepath clip newpath\n");
- break;
- }
- xshift(page);
- putsection(inf,0,secstart[0]);
- }
-
- void putpage(inf,pageno,npages)
- FILE *inf;
- int pageno, npages;
- {
- int nbytes;
-
- if(pageno<npages && pageno>=0) {
- nbytes = secend[pageno]-secstart[pageno];
- putsection(inf,secstart[pageno],nbytes);
- }
- }
-
- void dosave(inf)
- FILE *inf;
- {
- printf("gsave\n");
- }
-
- void dorestore(inf)
- FILE *inf;
- {
- if(trailstart)
- putsection(inf,trailstart,trailend-trailstart);
- printf("grestore\n");
- }
-
- void spreadpage(inf,x,y,sx,sy,page,pageno,npages)
- FILE *inf;
- int x, y;
- float sx, sy;
- int page, pageno, npages;
- {
- float pdx2;
-
- if(pageno<npages && pageno>=0) {
- pdx2 = 2*pdx;
- printf("gsave\n");
- printf("%f %f translate\n",SWIDTH,0.0);
- printf("90 rotate\n");
- if(page == SPLEFTPAGE)
- printf("%f %f translate\n",sx+x*(sx+pdx2)+0*pdx,sy+y*(sy+pdy));
- else
- printf("%f %f translate\n",sx+x*(sx+pdx2)+1*pdx,sy+y*(sy+pdy));
- printf("%f %f scale\n",pscale,pscale);
-
- dosave(inf);
- printf("newpath\n");
- printf("%f %f moveto\n",0.0,0.0);
- printf("%f %f lineto\n",pwidth,0.0);
- printf("%f %f lineto\n",pwidth,pheight);
- printf("%f %f lineto\n",0.0,pheight);
- printf("closepath clip newpath\n");
- xshift(pageno);
- putsection(inf,0,secstart[0]);
- putpage(inf,pageno,npages);
- dorestore(inf);
-
- printf("0.1 setlinewidth\n");
- printf("newpath\n");
- printf("%f %f moveto\n",0.0,0.0);
- printf("%f %f lineto\n",pwidth,0.0);
- printf("%f %f lineto\n",pwidth,pheight);
- printf("%f %f lineto\n",0.0,pheight);
- printf("closepath stroke\n");
- printf("grestore\n");
- }
- }
-
- void spread(inf,npages)
- FILE *inf;
- int npages;
- {
- int nx, ny, spreadsper, nspreads;
- int x, y, nsides, pageno, side;
- float sx, sy, spdx, spdy, pdx2;
-
-
- pdx2 = 2*pdx;
- spdx = SHEIGHT;
- spdy = SWIDTH;
- nx = (spdx-SPMARGIN)/(pdx2+SPMARGIN);
- ny = (spdy-SPMARGIN)/(pdy+SPMARGIN);
- sx = (spdx-nx*pdx2)/(nx+1);
- sy = (spdy-ny*pdy)/(ny+1);
- spreadsper = nx*ny;
- if(spreadsper <1) {
- fprintf(stderr,"psbook: try a smaller scale factor\n");
- exit(1);
- }
- nspreads = (npages+1)/2;
- nsides = ((nspreads-1)/spreadsper)+1;
- fprintf(stderr,"Spread array %d by %d\n",nx,ny);
- fprintf(stderr,"Printer sides %d\n",nsides);
-
- /* put out the sheets */
- pageno = -1;
- for(side=0; side<nsides; ) {
- printf("%%%%Page: page%d %d\n",side+1,side+1);
- for(y=0; y<ny; y++) {
- for(x=0; x<nx; x++) {
- spreadpage(inf,x,ny-1-y,sx,sy, SPLEFTPAGE,pageno+0,npages);
- spreadpage(inf,x,ny-1-y,sx,sy,SPRIGHTPAGE,pageno+1,npages);
- pageno+=2;
- }
- }
- printf("REALshowpage\n");
- side++;
- }
- }
-
- void sheettransform0(inf)
- FILE *inf;
- {
- }
-
- void fold0(inf,npages)
- FILE *inf;
- int npages;
- {
- int side, nsides, spages, pbase;
- float spdx, spdy;
-
- spdx = SWIDTH;
- spdy = SHEIGHT;
- nsides = npages;
- spages = nsides;
- fprintf(stderr,"FOLD 0: Printer sides %d\n",nsides);
-
- /* put out the sheets */
- for(side=0; side<nsides; ) {
- pbase = side;
-
- printf("%%%%Page: page%d %d\n",side+1,side+1);
- dosave(inf);
- sheettransform0(inf);
- setclip(inf,CENTERPAGE,spdx,spdy);
- putpage(inf,pbase,npages);
- dorestore(inf);
-
- printf("REALshowpage\n");
-
- side++;
- }
- }
-
- void printside(side)
- int side;
- {
- printf("/Times-Roman findfont 8 scalefont setfont\n");
- printf("72 15 moveto\n");
- if(side == FRONTSIDE)
- printf("(Front side) show\n");
- else
- printf("(Back side) show\n");
- }
-
- void sheettransform1(inf,side)
- FILE *inf;
- int side;
- {
- if(side == FRONTSIDE) {
- printf("%f %f translate\n",SWIDTH+FRONTXFUDGE,FRONTYFUDGE);
- printf("90 rotate\n");
- } else {
- printf("%f %f translate\n",BACKXFUDGE,SHEIGHT+BACKYFUDGE);
- printf("-90 rotate\n");
- }
- }
-
- void fold1(inf,npages)
- FILE *inf;
- int npages;
- {
- int side, nsides, spages, pbase;
- float spdx, spdy;
-
- spdx = SHEIGHT;
- spdy = SWIDTH;
- nsides = ((npages-1)/2)+1;
- if(nsides&1)
- nsides++;
- spages = nsides*2;
- fprintf(stderr,"FOLD 1: Printer sides %d\n",nsides);
- fprintf(stderr,"Book sheets %d\n",nsides/2);
-
- /* put out the sheets */
- for(side=0; side<nsides; ) {
- pbase = side;
-
- printf("%%%%Page: page%d %d\n",side+1,side+1);
- printside(FRONTSIDE);
- dosave(inf);
- sheettransform1(inf,FRONTSIDE);
- setclip(inf,RIGHTPAGE,spdx,spdy);
- putpage(inf,pbase,npages);
- dorestore(inf);
-
- dosave(inf);
- sheettransform1(inf,FRONTSIDE);
- setclip(inf,LEFTPAGE,spdx,spdy);
- putpage(inf,spages-1-pbase,npages);
- dorestore(inf);
-
- printf("REALshowpage\n");
-
- printf("%%%%Page: page%d %d\n",side+1,side+1);
- printside(BACKSIDE);
- dosave(inf);
- sheettransform1(inf,BACKSIDE);
- setclip(inf,LEFTPAGE,spdx,spdy);
- putpage(inf,pbase+1,npages);
- dorestore(inf);
-
- dosave(inf);
- sheettransform1(inf,BACKSIDE);
- setclip(inf,RIGHTPAGE,spdx,spdy);
- putpage(inf,spages-2-pbase,npages);
- dorestore(inf);
-
- printf("REALshowpage\n");
- side+=2;
- }
- }
-
- void sheettransform2(inf,side,sig)
- FILE *inf;
- int side, sig;
- {
- if(side == FRONTSIDE)
- printf("%f %f translate\n",FRONTXFUDGE,FRONTYFUDGE);
- else
- printf("%f %f translate\n",BACKXFUDGE,BACKYFUDGE);
- if(sig == TOPSIG)
- printf("0 %f translate\n",SHEIGHT/2.0);
- else {
- printf("%f %f translate\n",SWIDTH,SHEIGHT/2.0);
- printf("180 rotate\n");
- }
- putfold(SWIDTH/2.0-pdx,0.0,180.0);
- putfold(SWIDTH/2.0+pdx,0.0,0.0);
- }
-
- void fold2(inf,npages)
- FILE *inf;
- int npages;
- {
- int side, nsides, spages, pbase;
- float spdx, spdy;
-
- spdx = SWIDTH;
- spdy = SHEIGHT/2.0;
- nsides = ((npages-1)/4)+1;
- if(nsides&1)
- nsides++;
- spages = nsides*4;
- fprintf(stderr,"FOLD 2: Printer sides %d\n",nsides);
- fprintf(stderr,"Book sheets %d\n",nsides/2);
-
- /* put out the sides */
- for(side=0; side<nsides; ) {
- pbase = 2*side;
-
- printf("%%%%Page: page%d %d\n",side+1,side+1);
- printside(FRONTSIDE);
- dosave(inf);
- sheettransform2(inf,FRONTSIDE,TOPSIG);
- setclip(inf,RIGHTPAGE,spdx,spdy);
- putpage(inf,pbase,npages);
- dorestore(inf);
-
- dosave(inf);
- sheettransform2(inf,FRONTSIDE,TOPSIG);
- setclip(inf,LEFTPAGE,spdx,spdy);
- putpage(inf,spages-1-pbase,npages);
- dorestore(inf);
-
- dosave(inf);
- sheettransform2(inf,FRONTSIDE,BOTSIG);
- setclip(inf,RIGHTPAGE,spdx,spdy);
- putpage(inf,spages-4-pbase,npages);
- dorestore(inf);
-
- dosave(inf);
- sheettransform2(inf,FRONTSIDE,BOTSIG);
- setclip(inf,LEFTPAGE,spdx,spdy);
- putpage(inf,pbase+3,npages);
- dorestore(inf);
-
- printf("REALshowpage\n");
-
- printf("%%%%Page: page%d %d\n",side+1,side+1);
- printside(BACKSIDE);
- dosave(inf);
- sheettransform2(inf,BACKSIDE,TOPSIG);
- setclip(inf,LEFTPAGE,spdx,spdy);
- putpage(inf,pbase+1,npages);
- dorestore(inf);
-
- dosave(inf);
- sheettransform2(inf,BACKSIDE,TOPSIG);
- setclip(inf,RIGHTPAGE,spdx,spdy);
- putpage(inf,spages-2-pbase,npages);
- dorestore(inf);
-
- dosave(inf);
- sheettransform2(inf,BACKSIDE,BOTSIG);
- setclip(inf,LEFTPAGE,spdx,spdy);
- putpage(inf,spages-3-pbase,npages);
- dorestore(inf);
-
- dosave(inf);
- sheettransform2(inf,BACKSIDE,BOTSIG);
- setclip(inf,RIGHTPAGE,spdx,spdy);
- putpage(inf,pbase+2,npages);
- dorestore(inf);
-
- printf("REALshowpage\n");
- side+=2;
- }
- }
-
- main(argc,argv)
- int argc;
- char **argv;
- {
- FILE *inf;
- int npages, pagespread, i, dosettrans;
-
- if(argc<3) {
- fprintf(stderr,"\nusage: psbook in.ps pagescale [-pagespread] [-nosettrans]\n");
- fprintf(stderr," [-s pagedx pagedy] [-o xoffset yoffset dxoffset] > out.ps\n");
- fprintf(stderr,"\nThis will print two pages on each side of the paper: \n");
- fprintf(stderr," psbook in.ps 0.6 > out.ps\n");
- fprintf(stderr,"\nThis will print four pages on each side of the paper: \n");
- fprintf(stderr," psbook in.ps 0.45 > out.ps\n");
- fprintf(stderr,"\nThis will print page spreads across each sheet:\n");
- fprintf(stderr," psbook in.ps 0.28 -p > out.ps\n");
- fprintf(stderr,"\nSome printers support two sided printing. Here's the lp command:\n");
- fprintf(stderr," lp -o\"duplex 1\" out.ps\n");
- fprintf(stderr,"\n");
- exit(1);
- }
- pscale = atof(argv[2]);
- pwidth = DEFPWIDTH;
- pheight = DEFPHEIGHT;
- pagespread = 0;
- dosettrans = 1;
- for(i=3; i<argc; i++) {
- if(argv[i][0] == '-') {
- switch(argv[i][1]) {
- case 'p':
- pagespread = 1;
- break;
- case 's':
- i++;
- pwidth = 72.0*atof(argv[i]);
- i++;
- pheight = 72.0*atof(argv[i]);
- break;
- case 'o':
- i++;
- xoffset = 72.0*atof(argv[i]);
- i++;
- yoffset = 72.0*atof(argv[i]);
- i++;
- dxoffset = 72.0*atof(argv[i]);
- break;
- case 'n':
- dosettrans = 0;
- break;
- }
- }
- }
- if(pscale<0.001 || pscale > 10.0) {
- fprintf(stderr,"page scale should be between 0.001 and 1.0!!\n");
- exit(1);
- }
- inf = fopen(argv[1],"r");
- if(!inf) {
- fprintf(stderr,"psbook: can't open %s\n",argv[1]);
- exit(1);
- }
- npages = indexpages(inf);
-
- fprintf(stderr,"Document pages %d\n",npages);
-
- #ifdef DEBUG
- for(i=0; i<npages; i++)
- fprintf(stderr,"page %d start %d finish %d\n",i,secstart[i],secend[i]);
- fprintf(stderr,"trailstart %d trailend %d\n",trailstart,trailend);
- #endif
-
- if(npages == 0) {
- secend[0] = sizeoffile(inf);
- secstart[0] = 0;
- npages = 1;
- }
-
- /* put out the master preamble */
- psoutfile(stdout);
- printheader(dosettrans);
- printf("gsave\n");
- pdx = pwidth*pscale;
- pdy = pheight*pscale;
- if(pagespread) {
- spread(inf,npages);
- } else {
- if((pdx>FOLD1DX) || (pdy>FOLD1DY))
- fold0(inf,npages);
- else if((pdx>FOLD2DX) || (pdy>FOLD2DY))
- fold1(inf,npages);
- else
- fold2(inf,npages);
- }
- printf("grestore\n");
- printf("%%%%EOF\n");
- exit(0);
- }
-
-